import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName LC51
 * N皇后
 * @Author ykx
 * @Date 2024/3/27 7:44
 * @Version 1.0
 */
public class LC51 {
    public static void main(String[] args) {
        LC51 lc51 = new LC51();
        System.out.println(lc51.solveNQueens(4));
    }

    public List<List<String>> solveNQueens(int n) {
        // 初始化棋盘数组
        char[][] chess = new char[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                chess[i][j] = '.';
            }
        }
        List<List<String>> result = new ArrayList<>();
        solve(result, chess, 0);
        return result;
    }

    private List<String> toList(char[][] chess) {
        List<String> list = new ArrayList<>();
        for (char[] chars : chess) {
            list.add(new String(chars));
        }
        return list;
    }

    private void solve(List<List<String>> result, char[][] chess, int row) {
        if (row == chess.length) {
            // 递归出口
            result.add(toList(chess));
        } else {
            for (int col = 0; col < chess.length; col++) {
                // 判断能否继续放置皇后
                if (valid(chess, row, col)) {
                    // 数组复制一份
                    char[][] temp = copy(chess);
                    // 当前位置上放皇后
                    temp[row][col] = 'Q';
                    // 当前列符合条件，继续遍历下一行
                    solve(result, temp, row + 1);
                }
            }
        }
    }

    /**
     * 判断当前已走过的位置是否有效
     *
     * @param chess 棋盘
     * @param row   当前行
     * @param col   当前列
     * @return 是否有效
     */
    private boolean valid(char[][] chess, int row, int col) {
        // 坐标上面有没有皇后
        for (int i = 0; i < row; i++) {
            if (chess[i][col] == 'Q') {
                return false;
            }
        }

        // 判断主对角线上有没有皇后
        for (int i = row - 1, j = col + 1; i >= 0 && j < chess.length; i--, j++) {
            if (chess[i][j] == 'Q') {
                return false;
            }
        }

        // 判断副对角线上有没有皇后
        for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
            if (chess[i][j] == 'Q') {
                return false;
            }
        }

        return true;
    }

    /**
     * 拷贝数组
     *
     * @param chess 棋盘
     * @return char[][]
     */
    private char[][] copy(char[][] chess) {
        char[][] temp = new char[chess.length][chess.length];
        for (int i = 0; i < chess.length; i++) {
            System.arraycopy(chess[i], 0, temp[i], 0, chess.length);
        }
        return temp;
    }


}
